package com.qdxht.dispenser.utils;

import com.vi.vioserial.COMSerial;
import com.vi.vioserial.util.SerialDataUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import timber.log.Timber;

/**
 * 串口通信协议工具类
 */
public class SerialProtocolUtil {

    private static final String TAG = "SerialProtocolUtil";

    // 协议起始符
    private static final String START_CODE = "1F0F";

    // 命令类型
    public static final int CMD_READ_SENSOR = 0x01;  // 读设备传感器状态
    public static final int CMD_WRITE_CONFIG = 0x02; // 写配置参数
    public static final int CMD_READ_CONFIG = 0x03;  // 读配置参数
    public static final int CMD_DISPENSE = 0x04;     // 发袋命令
    public static final int CMD_ERROR_RECOVERY = 0x05; // 错误恢复

    // 状态类型
    public static final int STATUS_CRC_ERROR = 0x00;    // 返回CRC校验错误
    public static final int STATUS_READ_SENSOR = 0x01;  // 返回读传感器状态
    public static final int STATUS_WRITE_CONFIG = 0x02; // 返回写配置参数
    public static final int STATUS_READ_CONFIG = 0x03;  // 返回读配置参数
    public static final int STATUS_DISPENSE = 0x04;     // 返回发袋命令
    public static final int STATUS_ERROR_RECOVERY = 0x05; // 返回错误恢复
    public static final int STATUS_PROTOCOL_PARAM = 0x06; // 返回数据帧无效参数

    // 添加HEX数据发送监听器列表
    private static final List<OnHexDataSendListener> sendListeners = new ArrayList<>();

    /**
     * CRC校验表（从C语言版本转换而来）
     */
    private static final int[] CRCTAB = new int[] {
        0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011,
        0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022,
        0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,
        0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041,
        0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2,
        0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,
        0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1,
        0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082,
        0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192,
        0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1,
        0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1,
        0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,
        0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151,
        0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162,
        0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132,
        0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101,
        0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312,
        0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,
        0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371,
        0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342,
        0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1,
        0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2,
        0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2,
        0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,
        0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291,
        0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2,
        0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2,
        0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1,
        0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252,
        0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,
        0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231,
        0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202
    };

    /**
     * 计算CRC校验码
     * 从C语言版本转换为Java实现
     * 
     * @param data 字节数组数据
     * @param length 数据长度
     * @return CRC校验码
     */
    private static int crcCalc(byte[] data, int length) {
        int crc = 0;
        int combVal;
        
        for (int i = 0; i < length; i++) {
            // 在Java中需要将byte转为无符号值
            combVal = ((crc >> 8) & 0xFF) ^ (data[i] & 0xFF);
            crc = ((crc << 8) & 0xFFFF) ^ CRCTAB[combVal];
        }
        
        return crc & 0xFFFF; // 确保结果是16位无符号值
    }
    
    /**
     * 添加CRC校验码到数据末尾
     * 
     * @param data 字节数组数据
     * @param length 数据长度
     * @return 包含CRC的新数组
     */
    private static byte[] crcAdd(byte[] data, int length) {
        // 创建一个新数组，长度为原始数据长度+2（CRC占用2字节）
        byte[] result = new byte[length + 2];
        System.arraycopy(data, 0, result, 0, length);
        
        // 计算CRC值
        int crc = crcCalc(data, length);
        
        // 添加CRC到数据末尾（高字节在前，低字节在后）
        result[length] = (byte) ((crc >> 8) & 0xFF);
        result[length + 1] = (byte) (crc & 0xFF);
        
        return result;
    }

    /**
     * 计算CRC校验码
     * @param data 数据内容（16进制字符串）
     * @return CRC校验码（16进制字符串，2字节）
     */
    private static String calculateCRC(String data) {
        try {
            // 将16进制字符串转换为字节数组
            byte[] bytes = new byte[data.length() / 2];
            for (int i = 0; i < data.length(); i += 2) {
                bytes[i / 2] = (byte) Integer.parseInt(data.substring(i, i + 2), 16);
            }
            
            // 计算CRC
            int crc = crcCalc(bytes, bytes.length);
            
            // 返回16进制格式的CRC值（4个字符，2字节）
            return String.format("%04X", crc);
        } catch (Exception e) {
            Timber.tag(TAG).e(e, "CRC计算错误");
            return "0000"; // 出错时返回默认值
        }
    }

    /**
     * 发送读传感器状态命令
     * @param port 串口号
     * @param addr 设备地址
     * @param sensorType 传感器类型：01-侧边传感器状态，02-中间传感器状态，04-卡袋状态，05-全部错误状态查询
     * @return 是否发送成功
     */
    public static boolean sendReadSensor(String port, int addr, int sensorType) {
        // 参数检查
        if (sensorType != 0x01 && sensorType != 0x02 && sensorType != 0x04 && sensorType != 0x05) {
            Timber.tag(TAG).e("Invalid sensor type: %d", sensorType);
            return false;
        }

        // 构造数据帧 - 读传感器命令无数据部分，不需要低位在前转换
        String hexData = buildFrame(addr, CMD_READ_SENSOR, sensorType, "");

        // 发送数据
        return sendHexData(port, hexData, "读传感器状态");
    }

    /**
     * 发送写配置参数命令
     * @param port 串口号
     * @param addr 设备地址
     * @param configType 配置类型：01-设备波特率，05-预置票据数量，08-设置出袋速度
     * @param data 配置数据，十六进制字符串，根据实际数据长度确定（高位在前，将自动转换为低位在前）
     * @return 是否发送成功
     */
    public static boolean sendWriteConfig(String port, int addr, int configType, String data) {
        // 参数检查
        if ((configType != 0x01 && configType != 0x05 && configType != 0x08) || 
            (data == null || data.isEmpty())) {
            Timber.tag(TAG).e("Invalid config parameters: type=%d, data=%s", configType, data);
            return false;
        }

        // 确保data是偶数长度的十六进制字符串
        String normalizedData = data;
        if (normalizedData.length() % 2 != 0) {
            normalizedData = "0" + normalizedData; // 如果是奇数，前面补0
        }
        
        // 将数据转换为低位在前格式
        String littleEndianData = toLittleEndian(normalizedData);
        Timber.tag(TAG).d("原始数据: %s, 低位在前: %s", normalizedData, littleEndianData);

        // 构造数据帧
        String hexData = buildFrame(addr, CMD_WRITE_CONFIG, configType, littleEndianData);

        // 发送数据
        return sendHexData(port, hexData, "写配置参数");
    }

    /**
     * 发送读配置参数命令
     * @param port 串口号
     * @param addr 设备地址
     * @param configType 配置类型：01-读设备波特率，03-设备已发袋数，04-设备走纸里程
     *                  05-读剩余袋数，06-读固件版本，07-读设备型号，08-读当前发袋速度
     * @return 是否发送成功
     */
    public static boolean sendReadConfig(String port, int addr, int configType) {
        // 参数检查
        if (configType < 0x01 || configType > 0x08) {
            Timber.tag(TAG).e("Invalid config type: %d", configType);
            return false;
        }

        // 构造数据帧 - 读配置参数命令无数据部分，不需要低位在前转换
        String hexData = buildFrame(addr, CMD_READ_CONFIG, configType, "");

        // 发送数据
        return sendHexData(port, hexData, "读配置参数");
    }

    /**
     * 发送发袋命令
     * @param port 串口号
     * @param addr 设备地址
     * @param dispenserType 发袋类型：01-按寸设置袋子从手头发送到出袋口的长度，02-按cm设置袋子从手头发送到出袋口的长度
     * @param length 长度值（十六进制字符串，高位在前，将自动转换为低位在前）
     * @return 是否发送成功
     */
    public static boolean sendDispense(String port, int addr, int dispenserType, String length) {
        // 参数检查
        if (dispenserType != 0x01 && dispenserType != 0x02) {
            Timber.tag(TAG).e("Invalid dispenser type: %d", dispenserType);
            return false;
        }

        if (length == null || length.isEmpty()) {
            Timber.tag(TAG).e("Invalid length: %s", length);
            return false;
        }

        // 确保length是偶数长度的十六进制字符串
        String normalizedLength = length;
        if (normalizedLength.length() % 2 != 0) {
            normalizedLength = "0" + normalizedLength; // 如果是奇数，前面补0
        }
        
        // 将长度转换为低位在前格式
        String littleEndianLength = toLittleEndian(normalizedLength);
        Timber.tag(TAG).d("原始长度: %s, 低位在前: %s", normalizedLength, littleEndianLength);
        
        // 根据实际数据长度构造数据帧
        String hexData = buildFrame(addr, CMD_DISPENSE, dispenserType, littleEndianLength);

        // 发送数据
        return sendHexData(port, hexData, "发袋命令");
    }

    /**
     * 发送错误恢复命令
     * @param port 串口号
     * @param addr 设备地址
     * @param errorType 错误类型：02-恢复卡袋错误
     * @return 是否发送成功
     */
    public static boolean sendErrorRecovery(String port, int addr, int errorType) {
        // 参数检查
        if (errorType != 0x02) {
            Timber.tag(TAG).e("Invalid error type: %d", errorType);
            return false;
        }

        // 构造数据帧 - 错误恢复命令无数据部分，不需要低位在前转换
        String hexData = buildFrame(addr, CMD_ERROR_RECOVERY, errorType, "");

        // 发送数据
        return sendHexData(port, hexData, "错误恢复");
    }

    /**
     * 解析接收到的数据帧
     * 注意：该方法提取原始数据，实际数值解析（低位在前）由各个具体的解析方法完成
     * @param hexData 十六进制数据
     * @return 解析结果
     */
    public static ProtocolResult parseResponse(String hexData) {
        Timber.tag(TAG).d("解析数据: %s", hexData);

        if (hexData == null || hexData.length() < 14) {
            Timber.tag(TAG).e("数据长度不足: %s", hexData);
            return new ProtocolResult(false, "数据长度不足");
        }

        // 检查起始符
        String startCode = hexData.substring(0, 4);
        if (!START_CODE.equalsIgnoreCase(startCode)) {
            Timber.tag(TAG).e("起始符错误: %s", startCode);
            return new ProtocolResult(false, "起始符错误");
        }

        // 解析各字段
        try {
            int addr = Integer.parseInt(hexData.substring(4, 6), 16);
            int statusType = Integer.parseInt(hexData.substring(6, 8), 16);
            int statusParam = Integer.parseInt(hexData.substring(8, 10), 16);
            int dataLength = Integer.parseInt(hexData.substring(10, 12), 16);

            String data = "";
            if (dataLength > 0) {
                int dataStartPos = 12;
                int dataEndPos = dataStartPos + dataLength * 2;
                if (hexData.length() >= dataEndPos) {
                    data = hexData.substring(dataStartPos, dataEndPos);
                } else {
                    Timber.tag(TAG).e("数据长度不匹配: 声明长度=%d，实际数据不足", dataLength);
                    return new ProtocolResult(false, "数据长度不匹配");
                }
            }

            // 验证CRC校验码
            if (hexData.length() >= 12 + dataLength * 2 + 4) {
                int crcStartPos = 12 + dataLength * 2;
                String actualCrc = hexData.substring(crcStartPos, crcStartPos + 4);
                String dataPart = hexData.substring(0, crcStartPos);
                String expectedCrc = calculateCRC(dataPart);
                
                if (!actualCrc.equalsIgnoreCase(expectedCrc)) {
                    Timber.tag(TAG).e("CRC校验失败: 预期=%s，实际=%s", expectedCrc, actualCrc);
                    return new ProtocolResult(false, "CRC校验失败");
                }
            } else {
                Timber.tag(TAG).e("数据长度不足以包含CRC校验码");
                return new ProtocolResult(false, "数据不完整，缺少CRC校验码");
            }

            // 根据状态类型进行解析
            String message;
            boolean success = true;
            
            switch (statusType) {
                case STATUS_CRC_ERROR:
                    success = false;
                    message = "CRC校验错误";
                    break;
                case STATUS_READ_SENSOR:
                    message = parseSensorStatus(statusParam, data);
                    break;
                case STATUS_WRITE_CONFIG:
                    message = parseWriteConfigResult(statusParam, data);
                    break;
                case STATUS_READ_CONFIG:
                    message = parseConfigResult(statusParam, data);
                    break;
                case STATUS_DISPENSE:
                    message = parseDispenseResult(statusParam, data);
                    if(!"出袋成功".equals(message)){
                        success = false;
                    }
                    break;
                case STATUS_ERROR_RECOVERY:
                    message = parseErrorRecovery(statusParam, data);
                    if(!"卡袋子错误恢复成功".equals(message)){
                        success = false;
                    }
                    break;
                case STATUS_PROTOCOL_PARAM:
                    success = false;
                    message = "数据帧无效参数";
                    break;
                default:
                    success = false;
                    message = "未知状态类型: " + statusType;
            }

            ProtocolResult result = new ProtocolResult(success, message);
            result.setAddr(addr);
            result.setStatusType(statusType);
            result.setStatusParam(statusParam);
            result.setData(data);
            
            return result;
            
        } catch (Exception e) {
            Timber.tag(TAG).e(e, "解析数据出错");
            return new ProtocolResult(false, "解析数据出错: " + e.getMessage());
        }
    }

    /**
     * 解析传感器状态
     * 根据实际数据长度解析，低位在前
     */
    private static String parseSensorStatus(int param, String data) {
        if (data.isEmpty()) {
            return "读传感器状态成功，类型: " + param;
        }

        try {
            // 使用低位在前解析数据
            int statusValue = (int)parseLittleEndianHex(data);
            String status;
            
            switch (param) {
                case 1: // 侧边传感器
                    if (statusValue == 1) {
                        status = "侧边传感器无遮挡，无袋子存在";
                    } else if (statusValue == 0) {
                        status = "侧边传感器被遮挡，有袋子存在";
                    } else {
                        status = "侧边传感器未知状态: " + statusValue;
                    }
                    break;
                case 2: // 中间传感器
                    if (statusValue == 1) {
                        status = "中间传感器无遮挡";
                    } else if (statusValue == 0) {
                        status = "中间传感器被遮挡";
                    } else {
                        status = "中间传感器未知状态: " + statusValue;
                    }
                    break;
                case 4: // 卡袋状态
                    if (statusValue == 1) {
                        status = "处于卡袋状态";
                    } else if (statusValue == 0) {
                        status = "无卡袋情况";
                    } else {
                        status = "卡袋状态未知: " + statusValue;
                    }
                    break;
                case 5: // 全部错误状态
                    if (statusValue == 4) {
                        status = "处于卡袋状态";
                    } else if (statusValue == 2) {
                        status = "中间传感器无遮挡";
                    } else if (statusValue == 1) {
                        status = "侧边传感器无遮挡，无袋子存在";
                    } else if (statusValue == 0) {
                        status = "正常状态";
                    } else {
                        status = "错误状态未知: " + statusValue;
                    }
                    break;
                default:
                    status = "未知传感器类型: " + param + ", 状态值: " + statusValue;
            }
            return status;
        } catch (NumberFormatException e) {
            return "解析传感器状态失败: " + data;
        }
    }

    /**
     * 解析配置读取结果
     * 根据原始数据进行解析，低位在前
     */
    private static String parseConfigResult(int configType, String data) {
        if (data.isEmpty()) {
            return "读配置参数成功，类型: " + configType;
        }

        switch (configType) {
            case 1: // 波特率
                try {
                    // 不再假设数据长度，使用实际数据进行解析
                    int baudRate = (int)parseLittleEndianHex(data);
                    String baudRateValue = "未知";
                    if (baudRate == 0) {
                        baudRateValue = "4800";
                    } else if (baudRate == 1) {
                        baudRateValue = "9600";
                    } else if (baudRate == 2) {
                        baudRateValue = "19200";
                    } else {
                        baudRateValue = String.valueOf(baudRate);
                    }
                    return "设备波特率: " + baudRateValue;
                } catch (NumberFormatException e) {
                    return "解析波特率失败: " + data;
                }
                
            case 3: // 已发袋次数
                try {
                    long count = parseLittleEndianHex(data);
                    return "设备已发袋次数: " + count;
                } catch (NumberFormatException e) {
                    return "解析发袋次数失败: " + data;
                }
                
            case 4: // 走纸里程
                try {
                    long distance = parseLittleEndianHex(data);
                    return "设备走纸里程: " + distance + " 米";
                } catch (NumberFormatException e) {
                    return "解析走纸里程失败: " + data;
                }
                
            case 5: // 剩余袋数
                try {
                    long remaining = parseLittleEndianHex(data);
                    return "剩余袋子数量: " + remaining;
                } catch (NumberFormatException e) {
                    return "解析剩余袋数失败: " + data;
                }
                
            case 6: // 固件版本
                // 字符串类型，保持原样解析
                try {
                    return "固件版本: " + SerialDataUtils.hexStringToString(data);
                } catch (Exception e) {
                    return "解析固件版本失败: " + data;
                }
                
            case 7: // 设备型号
                // 字符串类型，保持原样解析
                try {
                    return "设备型号: " + SerialDataUtils.hexStringToString(data);
                } catch (Exception e) {
                    return "解析设备型号失败: " + data;
                }
                
            case 8: // 当前发袋速度
                try {
                    int speed = (int)parseLittleEndianHex(data);
                    return "当前发袋速度: " + speed + " mm/s";
                } catch (NumberFormatException e) {
                    return "解析发袋速度失败: " + data;
                }
                
            default:
                return "未知配置类型: " + configType + ", 数据: " + data;
        }
    }

    /**
     * 解析发袋命令结果
     * 根据实际数据长度解析，低位在前
     */
    private static String parseDispenseResult(int param, String data) {
        if (data.isEmpty()) {
            return "发袋命令接收成功，参数: " + param;
        }

        try {
            int statusValue = (int)parseLittleEndianHex(data);
            
            switch (statusValue) {
                case 0:
                    return "出袋成功";
                case 1:
                    return "出袋失败，原因是无袋子";
                case 4:
                    return "出袋失败，发生卡袋子状态";
                default:
                    return "未知出袋状态: " + statusValue;
            }
        } catch (NumberFormatException e) {
            return "解析出袋状态失败: " + data;
        }
    }

    /**
     * 解析错误恢复结果
     * 根据实际数据长度解析，低位在前
     */
    private static String parseErrorRecovery(int param, String data) {
        if (data.isEmpty() || param != 2) {
            return "错误恢复命令接收成功，参数: " + param;
        }

        try {
            int recoveryStatus = (int)parseLittleEndianHex(data);
            
            switch (recoveryStatus) {
                case 0:
                    return "卡袋子错误恢复成功";
                case 4:
                    return "卡袋子错误恢复失败";
                default:
                    return "未知恢复状态: " + recoveryStatus;
            }
        } catch (NumberFormatException e) {
            return "解析错误恢复状态失败: " + data;
        }
    }

    /**
     * 解析写配置参数结果
     * 结合协议表，返回详细的配置项类型、参数、含义等信息
     */
    private static String parseWriteConfigResult(int configType, String data) {
        StringBuilder sb = new StringBuilder();
        sb.append("写配置参数成功，类型: ").append(String.format("%02X", configType));
        switch (configType) {
            case 0x01:
                sb.append(" (设备波特率)");
                if (data != null && data.length() == 8) {
                    int baud = (int)parseLittleEndianHex(data);
                    String baudStr = "未知";
                    if (baud == 0) baudStr = "4800";
                    else if (baud == 1) baudStr = "9600";
                    else if (baud == 2) baudStr = "19200";
                    sb.append(", 设置为: ").append(baudStr);
                }
                break;
            case 0x05:
                sb.append(" (预置票据数量)");
                if (data != null && data.length() == 8) {
                    long preset = parseLittleEndianHex(data);
                    sb.append(", 设置为: ").append(preset);
                }
                break;
            case 0x08:
                sb.append(" (出袋速度)");
                if (data != null && data.length() == 8) {
                    int speed = (int)parseLittleEndianHex(data);
                    sb.append(", 设置为: ").append(speed).append(" mm/s");
                }
                break;
            default:
                sb.append(" (未知配置项)");
                if (data != null && !data.isEmpty()) {
                    sb.append(", Data: ").append(data);
                }
        }
        return sb.toString();
    }

    /**
     * 构建数据帧
     * @param addr 设备地址
     * @param cmdType 命令类型
     * @param cmdParam 命令参数
     * @param data 数据内容（16进制字符串，需要已经是低位在前格式）
     * @return 完整的数据帧16进制字符串
     */
    public static String buildFrame(int addr, int cmdType, int cmdParam, String data) {
        StringBuilder frame = new StringBuilder();
        
        // 起始符
        frame.append(START_CODE);
        
        // 设备地址
        frame.append(String.format("%02X", addr));
        
        // 命令类型
        frame.append(String.format("%02X", cmdType));
        
        // 命令参数
        frame.append(String.format("%02X", cmdParam));
        
        // 数据长度
        int dataLength = data.length() / 2; // 16进制字符串的长度除以2
        frame.append(String.format("%02X", dataLength));
        
        // 数据 (已经是低位在前格式)
        frame.append(data);
        
        // 计算CRC校验码
        String crc = calculateCRC(frame.toString());
        frame.append(crc);
        
        return frame.toString();
    }

    /**
     * 准备发送数据，将数据转换为低位在前格式
     * 这是一个公共方法，用于在应用程序的其他部分手动构建数据时使用
     * @param data 原始数据（高位在前）
     * @return 低位在前格式的数据
     */
    public static String prepareDataForSend(String data) {
        if (data == null || data.isEmpty()) {
            return "";
        }
        
        // 确保是偶数长度
        String normalizedData = data;
        if (normalizedData.length() % 2 != 0) {
            normalizedData = "0" + normalizedData; // 如果是奇数，前面补0
        }
        
        // 转换为低位在前格式
        return toLittleEndian(normalizedData);
    }
    
    /**
     * 发送十六进制数据
     * @param port 串口号
     * @param hexData 十六进制数据
     * @param operationName 操作名称（用于日志）
     * @return 是否发送成功
     */
    private static boolean sendHexData(String port, String hexData, String operationName) {
        try {
            Timber.tag(TAG).d("发送%s命令: %s", operationName, hexData);
            Timber.tag(TAG).d("发送数据格式化: %s", formatHexString(hexData));
            
            if (!COMSerial.instance().isOpen(port)) {
                Timber.tag(TAG).e("发送%s失败：串口%s未打开", operationName, port);
                return false;
            }
            
            // 发送数据
            COMSerial.instance().sendHex(port, hexData);
            
            // 通知监听器
            for (OnHexDataSendListener listener : sendListeners) {
                listener.onHexDataSent(port, hexData, operationName);
            }
            
            return true;
        } catch (Exception e) {
            Timber.tag(TAG).e(e, "发送%s出错", operationName);
            return false;
        }
    }

    /**
     * 添加十六进制数据发送监听器
     * @param listener 监听器
     */
    public static void addHexDataSendListener(OnHexDataSendListener listener) {
        if (listener != null && !sendListeners.contains(listener)) {
            sendListeners.add(listener);
        }
    }
    
    /**
     * 移除十六进制数据发送监听器
     * @param listener 监听器
     */
    public static void removeHexDataSendListener(OnHexDataSendListener listener) {
        if (listener != null) {
            sendListeners.remove(listener);
        }
    }
    
    /**
     * 清除所有监听器
     */
    public static void clearHexDataSendListeners() {
        sendListeners.clear();
    }
    
    /**
     * 格式化十六进制字符串，每两个字符之间添加空格
     * @param hexStr 原始十六进制字符串
     * @return 格式化后的字符串
     */
    public static String formatHexString(String hexStr) {
        if (hexStr == null || hexStr.isEmpty()) {
            return "";
        }
        
        StringBuilder formatted = new StringBuilder();
        for (int i = 0; i < hexStr.length(); i += 2) {
            if (i + 2 <= hexStr.length()) {
                formatted.append(hexStr.substring(i, i + 2)).append(" ");
            } else if (i < hexStr.length()) {
                formatted.append(hexStr.substring(i));
            }
        }
        return formatted.toString().trim();
    }
    
    /**
     * 解析十六进制数据为协议各部分
     * @param hexData 十六进制数据
     * @return 格式化的协议解析字符串
     */
    public static String parseHexProtocol(String hexData) {
        StringBuilder result = new StringBuilder();
        
        if (hexData == null || hexData.length() < 14) {
            return "数据长度不足，无法解析: " + hexData;
        }
        
        try {
            String startCode = hexData.substring(0, 4);
            int addr = Integer.parseInt(hexData.substring(4, 6), 16);
            int statusType = Integer.parseInt(hexData.substring(6, 8), 16);
            int statusParam = Integer.parseInt(hexData.substring(8, 10), 16);
            int dataLength = Integer.parseInt(hexData.substring(10, 12), 16);
            
            result.append("开始符: ").append(startCode).append("\n");
            result.append("地址: ").append(String.format("%02X", addr)).append("\n");
            result.append("类型: ").append(String.format("%02X", statusType)).append(" (");
            
            // 添加类型文字说明
            switch (statusType) {
                case STATUS_CRC_ERROR: result.append("CRC错误"); break;
                case STATUS_READ_SENSOR: result.append("读传感器状态"); break;
                case STATUS_WRITE_CONFIG: result.append("写配置参数"); break; 
                case STATUS_READ_CONFIG: result.append("读配置参数"); break;
                case STATUS_DISPENSE: result.append("发袋命令"); break;
                case STATUS_ERROR_RECOVERY: result.append("错误恢复"); break;
                case STATUS_PROTOCOL_PARAM: result.append("协议参数错误"); break;
                default: result.append("未知");
            }
            result.append(")\n");
            
            result.append("参数: ").append(String.format("%02X", statusParam)).append("\n");
            result.append("数据长度: ").append(dataLength).append(" 字节\n");
            
            // 处理可变长度的数据
            if (dataLength > 0) {
                int dataStartPos = 12;
                int dataEndPos = dataStartPos + dataLength * 2;
                if (hexData.length() >= dataEndPos) {
                    String data = hexData.substring(dataStartPos, dataEndPos);
                    result.append("数据: ").append(data);
                    
                    // 对于数值类型的数据，显示低位在前解析结果
                    try {
                        // 除了字符串型数据（如固件版本和设备型号），其他数据都尝试以低位在前解析
                        boolean isStringData = (statusType == STATUS_READ_CONFIG && 
                                             (statusParam == 6 || statusParam == 7));
                        
                        if (!isStringData && dataLength <= 8) {
                            long value = parseLittleEndianHex(data);
                            result.append(" (低位在前解析值: ").append(value).append(")");
                        }
                    } catch (Exception e) {
                        // 解析失败，忽略
                    }
                    
                    // 如果是具有特定含义的数据，尝试进一步解析
                    switch (statusType) {
                        case STATUS_READ_SENSOR:
                            String sensorInfo = parseSensorStatus(statusParam, data);
                            result.append(" (").append(sensorInfo).append(")");
                            break;
                        case STATUS_READ_CONFIG:
                            String configInfo = parseConfigResult(statusParam, data);
                            result.append(" (").append(configInfo).append(")");
                            break;
                        case STATUS_DISPENSE:
                            String dispenseInfo = parseDispenseResult(statusParam, data);
                            result.append(" (").append(dispenseInfo).append(")");
                            break;
                        case STATUS_ERROR_RECOVERY:
                            String recoveryInfo = parseErrorRecovery(statusParam, data);
                            result.append(" (").append(recoveryInfo).append(")");
                            break;
                    }
                    
                    result.append("\n");
                } else {
                    result.append("数据: 长度不匹配，声明长度=").append(dataLength).append("，实际数据不足\n");
                }
            }
            
            // CRC校验码
            if (hexData.length() >= 12 + dataLength * 2 + 4) {
                int crcStartPos = 12 + dataLength * 2;
                String actualCrc = hexData.substring(crcStartPos, crcStartPos + 4);
                String dataPart = hexData.substring(0, crcStartPos);
                String expectedCrc = calculateCRC(dataPart);
                
                result.append("CRC: ").append(actualCrc);
                if (!actualCrc.equalsIgnoreCase(expectedCrc)) {
                    result.append(" (校验失败，预期=").append(expectedCrc).append(")");
                }
            } else {
                result.append("CRC: 数据不完整，缺少CRC校验码");
            }
            
        } catch (Exception e) {
            return "解析失败: " + e.getMessage();
        }
        
        return result.toString();
    }
    
    /**
     * 十六进制数据发送监听接口
     */
    public interface OnHexDataSendListener {
        /**
         * 当十六进制数据被发送时调用
         * @param port 串口号
         * @param hexData 十六进制数据
         * @param operationName 操作名称
         */
        void onHexDataSent(String port, String hexData, String operationName);
    }

    /**
     * 协议解析结果类
     */
    public static class ProtocolResult {
        private boolean success;
        private String message;
        private int addr;
        public int statusType;
        private int statusParam;
        private String data;

        public ProtocolResult(boolean success, String message) {
            this.success = success;
            this.message = message;
        }

        public boolean isSuccess() {
            return success;
        }

        public String getMessage() {
            return message;
        }

        public int getAddr() {
            return addr;
        }

        public void setAddr(int addr) {
            this.addr = addr;
        }

        public int getStatusType() {
            return statusType;
        }

        public void setStatusType(int statusType) {
            this.statusType = statusType;
        }

        public int getStatusParam() {
            return statusParam;
        }

        public void setStatusParam(int statusParam) {
            this.statusParam = statusParam;
        }

        public String getData() {
            return data;
        }

        public void setData(String data) {
            this.data = data;
        }

        @Override
        public String toString() {
            return String.format("ProtocolResult{success=%s, message='%s', addr=%d, statusType=%d, statusParam=%d, data='%s'}",
                    success, message, addr, statusType, statusParam, data);
        }
    }

    /**
     * 反转字节顺序（低位在前转高位在前）
     * 例如："1234" -> "3412"
     * @param hexString 十六进制字符串
     * @return 反转字节顺序后的字符串
     */
    private static String reverseByteOrder(String hexString) {
        if (hexString == null || hexString.isEmpty() || hexString.length() % 2 != 0) {
            return hexString;
        }
        
        StringBuilder reversed = new StringBuilder();
        for (int i = hexString.length() - 2; i >= 0; i -= 2) {
            reversed.append(hexString.substring(i, i + 2));
        }
        return reversed.toString();
    }
    
    /**
     * 解析低位在前格式的十六进制字符串为长整型
     * @param hexString 十六进制字符串（低位在前）
     * @return 解析后的长整型值
     */
    private static long parseLittleEndianHex(String hexString) {
        String bigEndian = reverseByteOrder(hexString);
        return Long.parseLong(bigEndian, 16);
    }

    /**
     * 将十六进制字符串转换为低位在前格式
     * @param hexString 原始十六进制字符串（高位在前）
     * @return 低位在前格式的十六进制字符串
     */
    private static String toLittleEndian(String hexString) {
        if (hexString == null || hexString.isEmpty() || hexString.length() % 2 != 0) {
            return hexString; // 处理无效输入
        }
        return reverseByteOrder(hexString);
    }
} 